home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / ftpserv.c < prev    next >
C/C++ Source or Header  |  1993-07-30  |  21KB  |  842 lines

  1. /* Internet FTP Server server machine - see RFC 959
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <time.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #ifdef    __TURBOC__
  10. #include <io.h>
  11. #include <dir.h>
  12. #endif
  13. #include "global.h"
  14. #include "config.h"
  15. #include "mbuf.h"
  16. #include "socket.h"
  17. #include "ftp.h"
  18. #include "ftpserv.h"
  19. #include "proc.h"
  20. #include "dirutil.h"
  21. #include "files.h"
  22. #include "commands.h"
  23. #ifdef CALLSERVER
  24. #include <string.h>
  25. /* CD-ROM code by Fred Peachman KB7YW */
  26. extern char *CDROM; /* buckbook.c: defines CDROM drive letter e.g. "s:"  */
  27. #endif                  /* #ifdef CALLSERVER  */
  28.  
  29. static void ftpserv __ARGS((int s,void *unused,void *p));
  30. static int pport __ARGS((struct sockaddr_in *sock,char *arg));
  31. static void ftplogin __ARGS((struct ftpserv *ftp,char *pass));
  32. static int sendit __ARGS((struct ftpserv *ftp,char *command,char *file));
  33. static int recvit __ARGS((struct ftpserv *ftp,char *command,char *file));
  34. int doftptdisc __ARGS((int argc, char *argv[], void *p));
  35.  
  36. /* Command table */
  37. static char *commands[] = {
  38.     "user",
  39.     "acct",
  40.     "pass",
  41.     "type",
  42.     "list",
  43.     "cwd",
  44.     "dele",
  45.     "name",
  46.     "quit",
  47.     "retr",
  48.     "stor",
  49.     "port",
  50.     "nlst",
  51.     "pwd",
  52.     "xpwd",            /* For compatibility with 4.2BSD */
  53.     "mkd ",
  54.     "xmkd",            /* For compatibility with 4.2BSD */
  55.     "xrmd",            /* For compatibility with 4.2BSD */
  56.     "rmd ",
  57.     "stru",
  58.     "mode",
  59.     NULLCHAR
  60. };
  61.  
  62. /* Response messages */
  63. static char banner[] = "220- %s, KA9Q-NOS FTP version %s\n";
  64. static char banner1[] = "220  Ready on %s";
  65. static char badcmd[] = "500 Unknown command\n";
  66. static char binwarn[] = "100 Warning: type is ASCII and %s appears to be binary\n";
  67. static char unsupp[] = "500 Unsupported command or option\n";
  68. static char givepass[] = "331 Enter PASS command\n";
  69. static char logged[] = "230 Logged in\n";
  70. static char loggeda[] = "230 Logged in as anonymous, restrictions apply\n";
  71. static char typeok[] = "200 Type %s OK\n";
  72. static char only8[] = "501 Only logical bytesize 8 supported\n";
  73. static char deleok[] = "250 File deleted\n";
  74. static char mkdok[] = "200 MKD ok\n";
  75. static char delefail[] = "550 Delete failed: %s\n";
  76. static char pwdmsg[] = "257 \"%s\" is current directory\n";
  77. static char badtype[] = "501 Unknown type \"%s\"\n";
  78. static char badport[] = "501 Bad port syntax\n";
  79. static char unimp[] = "502 Command not yet implemented\n";
  80. static char bye[] = "221 Goodbye!\n";
  81. static char nodir[] = "553 Can't read directory \"%s\": %s\n";
  82. static char cantopen[] = "550 Can't read file \"%s\": %s\n";
  83. static char sending[] = "150 Opening data connection for %s %s\n";
  84. static char cantmake[] = "553 Can't create \"%s\": %s\n";
  85. static char writerr[] = "552 Write error: %s\n";
  86. static char portok[] = "200 Port command okay\n";
  87. static char rxok[] = "226 File received OK\n";
  88. static char txok[] = "226 File sent OK\n";
  89. static char noperm[] = "550 Permission denied\n";
  90. static char noconn[] = "425 Data connection reset\n";
  91. static char lowmem[] = "421 System overloaded, try again later\n";
  92. static char notlog[] = "530 Please log in with USER and PASS\n";
  93. static char userfirst[] = "503 Login with USER first.\n";
  94. static char okay[] = "200 Ok\n";
  95.  
  96. static int Sftp = -1;    /* Prototype socket for service */
  97.  
  98. #ifdef FTPTDISC
  99. int32 Ftptdiscinit = 0;
  100.  
  101. /* Set ftp redundancy timer */
  102. int
  103. doftptdisc(argc,argv,p)
  104. int argc;
  105. char *argv[];
  106. void *p;
  107. {
  108.     return setlong(&Ftptdiscinit,"Ftp redundancy timer (sec)",argc,argv);
  109. }
  110.  
  111. static void
  112. ftp_redundant(ftp)
  113. struct ftpserv *ftp;
  114. {
  115.     /* Clean up */
  116.     shutdown(ftp->control,2);
  117.     close_s(ftp->control);
  118.     if(ftp->data != -1){
  119.         shutdown(ftp->data,2);
  120.         close_s(ftp->data);
  121.         ftp->data = -1;
  122.     }
  123.     return;
  124. }
  125. #endif
  126.  
  127. /* Start up FTP service */
  128. int
  129. ftpstart(argc,argv,p)
  130. int argc;
  131. char *argv[];
  132. void *p;
  133. {
  134.     struct sockaddr_in lsocket;
  135.     int s;
  136.  
  137.     if(Sftp != -1){
  138.         /* Already running! */
  139.         return 0;
  140.     }
  141.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  142.     chname(Curproc,"FTP listener");
  143.  
  144.     lsocket.sin_family = AF_INET;
  145.     lsocket.sin_addr.s_addr = INADDR_ANY;
  146.     if(argc < 2)
  147.         lsocket.sin_port = IPPORT_FTP;
  148.     else
  149.         lsocket.sin_port = atoi(argv[1]);
  150.  
  151.     Sftp = socket(AF_INET,SOCK_STREAM,0);
  152.     bind(Sftp,(char *)&lsocket,sizeof(lsocket));
  153.     listen(Sftp,1);
  154.     for(;;){
  155.         if((s = accept(Sftp,NULLCHAR,(int *)NULL)) == -1)
  156.             break;    /* Service is shutting down */
  157.         /* Low mem check now done in tcpin.c - WG7J */
  158.         /* Spawn a server */
  159.         newproc("ftpserv",2048,ftpserv,s,NULL,NULL,0);
  160.     }
  161.     return 0;
  162. }
  163. static void
  164. ftpserv(s,unused,p)
  165. int s;    /* Socket with user connection */
  166. void *unused;
  167. void *p;
  168. {
  169.     struct ftpserv ftp;
  170.     char **cmdp,buf[512],*arg,*cp,*cp1,*file,*mode;
  171.     long t;
  172.     int cnt,i;
  173.     struct sockaddr_in socket;
  174.  
  175.     extern char *Ftp_motd;
  176.  
  177.     sockmode(s,SOCK_ASCII);
  178.     memset((char *)&ftp,0,sizeof(ftp));    /* Start with clear slate */
  179.     ftp.data = -1;
  180.  
  181.     sockowner(s,Curproc);        /* We own it now */
  182.     ftp.control = s;
  183.     /* Set default data port */
  184.     i = SOCKSIZE;
  185.     getpeername(s,(char *)&socket,&i);
  186.     socket.sin_port = IPPORT_FTPD;
  187.     ASSIGN(ftp.port,socket);
  188.  
  189. #ifdef FTPTDISC
  190.     /* Set the timeout timer - WG7J */
  191.     set_timer(&ftp.tdisc,Ftptdiscinit * 1000L);
  192.     ftp.tdisc.func = ftp_redundant;
  193.     ftp.tdisc.arg = &ftp;
  194.     start_timer(&ftp.tdisc);
  195. #endif
  196.  
  197.     log(s,"open FTP");
  198.     usprintf(s,banner,Hostname,Version);
  199.     if(Ftp_motd != NULLCHAR){
  200.         if((cp1 = strchr(Ftp_motd,'\n')) == NULLCHAR){
  201.             usprintf(s,"220- %s\n",Ftp_motd);
  202.         } else {
  203.             cp=mallocw(strlen(Ftp_motd)+2);
  204.            cp1 = cp;
  205.             for(cnt=0;cnt<=strlen(Ftp_motd);cnt++){
  206.             if(Ftp_motd[cnt] != '\n'){
  207.                 *cp1 = Ftp_motd[cnt];
  208.                 cp1++;
  209.             } else {
  210.                 *cp1 = '\n';
  211.                 cp1++;
  212.                 *cp1 = '\0';
  213.                 usprintf(s,"220- %s",cp);
  214.                 cp1 = cp;
  215.             }
  216.            }
  217.            free(cp);
  218.         }
  219.     }
  220.     time(&t);
  221.     cp = ctime(&t);
  222. #ifdef notdef
  223.     if((cp1 = strchr(cp,'\n')) != NULLCHAR)
  224.         *cp1 = '\0';
  225. #endif
  226.     usprintf(s,banner1,cp);
  227.  
  228.     /* Command interpreting loop */
  229. loop:
  230.     if((cnt = recvline(s,buf,sizeof(buf))) == -1){
  231.         /* He closed on us */
  232.         goto finish;
  233.     }
  234. #ifdef FTPTDISC
  235.     /* Reset the timeout timer - WG7J */
  236.     start_timer(&ftp.tdisc);
  237. #endif
  238.     if(cnt == 0){
  239.         /* Can't be a legal FTP command */
  240.         usprintf(ftp.control,badcmd);
  241.         goto loop;
  242.     }    
  243.     rip(buf);
  244. #ifdef    UNIX
  245.     /* Translate first word to lower case */
  246.     for(cp = buf;*cp != ' ' && *cp != '\0';cp++)
  247.         *cp = tolower(*cp);
  248. #else
  249.     /* Translate entire buffer to lower case */
  250.     for(cp = buf;*cp != '\0';cp++)
  251.         *cp = tolower(*cp);
  252. #endif
  253.     /* Find command in table; if not present, return syntax error */
  254.     for(cmdp = commands;*cmdp != NULLCHAR;cmdp++)
  255.         if(strncmp(*cmdp,buf,strlen(*cmdp)) == 0)
  256.             break;
  257.     if(*cmdp == NULLCHAR){
  258.         usprintf(ftp.control,badcmd);
  259.         goto loop;
  260.     }
  261.     /* Allow only USER, PASS and QUIT before logging in */
  262.     if(ftp.cd == NULLCHAR || ftp.path == NULLCHAR){
  263.         switch(cmdp-commands){
  264.         case USER_CMD:
  265.         case PASS_CMD:
  266.         case QUIT_CMD:
  267.             break;
  268.         default:
  269.             usprintf(ftp.control,notlog);
  270.             goto loop;
  271.         }
  272.     }
  273.     arg = &buf[strlen(*cmdp)];
  274.     while(*arg == ' ')
  275.         arg++;
  276.  
  277.     /* Execute specific command */
  278.     switch(cmdp-commands){
  279.     case USER_CMD:
  280.         free(ftp.username);
  281.         ftp.username = strdup(arg);
  282.         usprintf(ftp.control,givepass);
  283.         break;
  284.     case TYPE_CMD:
  285.         switch(arg[0]){
  286.         case 'A':
  287.         case 'a':    /* Ascii */
  288.             ftp.type = ASCII_TYPE;
  289.             usprintf(ftp.control,typeok,arg);
  290.             break;
  291.         case 'l':
  292.         case 'L':
  293.             while(*arg != ' ' && *arg != '\0')
  294.                 arg++;
  295.             if(*arg == '\0' || *++arg != '8'){
  296.                 usprintf(ftp.control,only8);
  297.                 break;
  298.             }
  299.             ftp.type = LOGICAL_TYPE;
  300.             ftp.logbsize = 8;
  301.             usprintf(ftp.control,typeok,arg);
  302.             break;
  303.         case 'B':
  304.         case 'b':    /* Binary */
  305.         case 'I':
  306.         case 'i':    /* Image */
  307.             ftp.type = IMAGE_TYPE;
  308.             usprintf(ftp.control,typeok,arg);
  309.             break;
  310.         default:    /* Invalid */
  311.             usprintf(ftp.control,badtype,arg);
  312.             break;
  313.         }
  314.         break;
  315.     case QUIT_CMD:
  316.         usprintf(ftp.control,bye);
  317.         goto finish;
  318.     case RETR_CMD:
  319.         file = pathname(ftp.cd,arg);
  320.         switch(ftp.type){
  321.         case IMAGE_TYPE:
  322.         case LOGICAL_TYPE:
  323.             mode = READ_BINARY;
  324.             break;
  325.         case ASCII_TYPE:
  326.             mode = READ_TEXT;
  327.             break;
  328.         }
  329.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  330.              usprintf(ftp.control,noperm);
  331.         } else if((ftp.fp = fopen(file,mode)) == NULLFILE){
  332.             usprintf(ftp.control,cantopen,file, strerror(errno));
  333.         } else {
  334.             log(ftp.control,"RETR %s",file);
  335.             if(ftp.type == ASCII_TYPE && isbinary(ftp.fp)){
  336.                 usprintf(ftp.control,binwarn,file);
  337.             }
  338.             sendit(&ftp,"RETR",file);
  339.         }
  340.         free(file);
  341.         break;
  342.     case STOR_CMD:
  343.         file = pathname(ftp.cd,arg);
  344.         switch(ftp.type){
  345.         case IMAGE_TYPE:
  346.         case LOGICAL_TYPE:
  347.             mode = WRITE_BINARY;
  348.             break;
  349.         case ASCII_TYPE:
  350.             mode = WRITE_TEXT;
  351.             break;
  352.         }
  353.         if(!permcheck(ftp.path,ftp.perms,STOR_CMD,file)){
  354.              usprintf(ftp.control,noperm);
  355.         } else if((ftp.fp = fopen(file,mode)) == NULLFILE){
  356.             usprintf(ftp.control,cantmake,file, strerror(errno));
  357.         } else {
  358.             log(ftp.control,"STOR %s",file);
  359.             recvit(&ftp,"STOR",file);
  360.         }
  361.         free(file);
  362.         break;
  363.     case PORT_CMD:
  364.         if(pport(&ftp.port,arg) == -1){
  365.             usprintf(ftp.control,badport);
  366.         } else {
  367.             usprintf(ftp.control,portok);
  368.         }
  369.         break;
  370. #ifndef CPM
  371.     case LIST_CMD:
  372.         file = pathname(ftp.cd,arg);
  373.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  374.              usprintf(ftp.control,noperm);
  375.         } else if((ftp.fp = dir(file,1)) == NULLFILE){
  376.             usprintf(ftp.control,nodir,file, strerror(errno));
  377.         } else {
  378.             sendit(&ftp,"LIST",file);
  379.         }
  380.         free(file);
  381.         break;
  382.     case NLST_CMD:
  383.         file = pathname(ftp.cd,arg);
  384.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  385.              usprintf(ftp.control,noperm);
  386.         } else if((ftp.fp = dir(file,0)) == NULLFILE){
  387.             usprintf(ftp.control,nodir,file, strerror(errno));
  388.         } else {
  389.             sendit(&ftp,"NLST",file);
  390.         }
  391.         free(file);
  392.         break;
  393.     case CWD_CMD:
  394. #ifdef CALLSERVER
  395. /* if the requested path contains the CROM drive letter:  */
  396.     if (CDROM != NULLCHAR && strncmp(CDROM, arg, 2) == 0)  {
  397.       if (strchr(arg, '/') == NULLCHAR) {
  398.         file = (char *)malloc(strlen(arg) + 2);
  399.         sprintf(file,"%s/", arg);
  400.       }
  401.       else  file = strdup(arg);
  402.     if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file))
  403.         {
  404.         usprintf(ftp.control,noperm);
  405.         free(file);
  406.         /* Don'tcha just LOVE %%$#@!! MS-DOS? - which is what we are running */
  407.         }
  408.     else 
  409.         if(file[2] == '/' || access(file,0) == 0)
  410.             {
  411.             /* Succeeded, record in control block */
  412.             free(ftp.cd);
  413.             ftp.cd = file;
  414.             usprintf(ftp.control,"You may return to your default drive & directory by entering:\n\t\t\"cd %s\"\n\n", ftp.path);
  415.             usprintf(ftp.control,pwdmsg,file);
  416.             }
  417.         else
  418.             {
  419.             /* Failed, don't change anything */
  420.             usprintf(ftp.control,nodir,file,sys_errlist[errno]);
  421.             free(file);
  422.             }
  423.     break;
  424.     }
  425. /* requested path does not contain CDROM drive letter:                      */
  426.     /* if current dir is in CDROM - and a "off-root" is requested:
  427.         go back to default path.
  428.      */
  429.     if ((CDROM != NULLCHAR && strncmp(ftp.cd, CDROM, 2) == 0) &&
  430.         (arg[0] == '/'))  {
  431.       free(ftp.cd);
  432.       ftp.cd = strdup(ftp.path);      /* go back to default path            */
  433.     }
  434. #endif  /* #ifdef CALLSERVER  */
  435.         file = pathname(ftp.cd,arg);
  436.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file))
  437.             {
  438.             usprintf(ftp.control,noperm);
  439.             free(file);
  440. #ifdef    MSDOS
  441.         /* Don'tcha just LOVE %%$#@!! MS-DOS? */
  442.             }
  443.         else 
  444.             if(strcmp(file,"/") == 0 ||
  445.                access(file,0) == 0)
  446.                 {
  447. #else
  448.             } 
  449.             else
  450.                 if(access(file,0) == 0)
  451.                     {    /* See if it exists */
  452. #endif
  453.                     /* Succeeded, record in control block */
  454.                     free(ftp.cd);
  455.                     ftp.cd = file;
  456.                     usprintf(ftp.control,pwdmsg,file);
  457.                     } 
  458.                 else
  459.                     {
  460.                     /* Failed, don't change anything */
  461.                     usprintf(ftp.control,nodir,file, strerror(errno));
  462.                     free(file);
  463.                     }
  464.         break;
  465.     case XPWD_CMD:
  466.     case PWD_CMD:
  467.         cp = strdup(ftp.cd);
  468.         if((cp1 = strchr(cp,';')) != NULLCHAR)
  469.             *cp1 = '\0';
  470.         usprintf(ftp.control,pwdmsg,cp);
  471.         free(cp);
  472.         break;
  473. #else
  474.     case LIST_CMD:
  475.     case NLST_CMD:
  476.     case CWD_CMD:
  477.     case XPWD_CMD:
  478.     case PWD_CMD:
  479. #endif
  480.     case ACCT_CMD:        
  481.         usprintf(ftp.control,unimp);
  482.         break;
  483.     case DELE_CMD:
  484.         file = pathname(ftp.cd,arg);
  485.         if(!permcheck(ftp.path,ftp.perms,DELE_CMD,file)){
  486.              usprintf(ftp.control,noperm);
  487.         } else if(remove(file) == 0){
  488.             log(ftp.control,"DELE %s",file);
  489.             usprintf(ftp.control,deleok);
  490.         } else {
  491.             usprintf(ftp.control,delefail, strerror(errno));
  492.         }
  493.         free(file);
  494.         break;
  495.     case PASS_CMD:
  496.         if(ftp.username == NULLCHAR)
  497.             usprintf(ftp.control,userfirst);
  498.         else
  499.             ftplogin(&ftp,arg);            
  500.         break;
  501. #ifndef    CPM
  502.     case XMKD_CMD:
  503.     case MKD_CMD:
  504.         file = pathname(ftp.cd,arg);
  505.         if(!permcheck(ftp.path,ftp.perms,MKD_CMD,file)){
  506.             usprintf(ftp.control,noperm);
  507. #ifdef    UNIX
  508.         } else if(mkdir(file,0777) == 0){
  509. #else
  510.         } else if(mkdir(file) == 0){
  511. #endif
  512.             log(ftp.control,"MKD %s",file);
  513.             usprintf(ftp.control,mkdok);
  514.         } else {
  515.             usprintf(ftp.control,cantmake,file, strerror(errno));
  516.         }
  517.         free(file);
  518.         break;
  519.     case XRMD_CMD:
  520.     case RMD_CMD:
  521.         file = pathname(ftp.cd,arg);
  522.         if(!permcheck(ftp.path,ftp.perms,RMD_CMD,file)){
  523.              usprintf(ftp.control,noperm);
  524.         } else if(rmdir(file) == 0){
  525.             log(ftp.control,"RMD %s",file);
  526.             usprintf(ftp.control,deleok);
  527.         } else {
  528.             usprintf(ftp.control,delefail, strerror(errno));
  529.         }
  530.         free(file);
  531.         break;
  532.     case STRU_CMD:
  533.         if(tolower(arg[0]) != 'f')
  534.             usprintf(ftp.control,unsupp);
  535.         else
  536.             usprintf(ftp.control,okay);
  537.         break;
  538.     case MODE_CMD:
  539.         if(tolower(arg[0]) != 's')
  540.             usprintf(ftp.control,unsupp);
  541.         else
  542.             usprintf(ftp.control,okay);
  543.         break;
  544.     }
  545. #endif
  546.     goto loop;
  547. finish:
  548.  
  549. #ifdef FTPTDISC
  550.     stop_timer(&ftp.tdisc);
  551. #endif
  552.  
  553.     log(ftp.control,"close FTP");
  554.     /* Clean up */
  555.     close_s(ftp.control);
  556.     if(ftp.data != -1)
  557.         close_s(ftp.data);
  558.     if(ftp.fp != NULLFILE)
  559.         fclose(ftp.fp);
  560.     free(ftp.username);
  561.     free(ftp.path);
  562.     free(ftp.cd);
  563. }
  564.  
  565. /* Shut down FTP server */
  566. int
  567. ftp0(argc,argv,p)
  568. int argc;
  569. char *argv[];
  570. void *p;
  571. {
  572.     close_s(Sftp);
  573.     Sftp = -1;
  574.     return 0;
  575. }
  576. static
  577. int
  578. pport(sock,arg)
  579. struct sockaddr_in *sock;
  580. char *arg;
  581. {
  582.     int32 n;
  583.     int i;
  584.  
  585.     n = 0;
  586.     for(i=0;i<4;i++){
  587.         n = atoi(arg) + (n << 8);
  588.         if((arg = strchr(arg,',')) == NULLCHAR)
  589.             return -1;
  590.         arg++;
  591.     }
  592.     sock->sin_addr.s_addr = n;
  593.     n = atoi(arg);
  594.     if((arg = strchr(arg,',')) == NULLCHAR)
  595.         return -1;
  596.     arg++;
  597.     n = atoi(arg) + (n << 8);
  598.     sock->sin_port = n;
  599.     return 0;
  600. }
  601.  
  602. /* Attempt to log in the user whose name is in ftp->username and password
  603.  * in pass
  604.  */
  605. static void
  606. ftplogin(ftp,pass)
  607. struct ftpserv *ftp;
  608. char *pass;
  609. {
  610.     char *path;
  611.     char *p;
  612.     int anony = 0;
  613.  
  614.     path = mallocw(200);
  615.     if((ftp->perms = userlogin(ftp->username,pass,&path,200,&anony))
  616.        == -1){
  617.         usprintf(ftp->control,noperm);
  618.         free(path);
  619.         return;
  620.     }
  621.     /* Set up current directory and path prefix */
  622. #if    defined(AMIGAGONE)
  623.     ftp->cd = pathname("", path);
  624.     ftp->path = strdup(ftp->cd);
  625.     free(path);
  626. #else
  627.     ftp->cd = path;
  628.     ftp->path = strdup(path);
  629.     if((p = strchr(path,';')) != '\0')
  630.         *p = '\0';        /* delimit initial cd */
  631. #endif
  632.  
  633.     if(!anony){
  634.         usprintf(ftp->control,logged);
  635.         log(ftp->control,"%s logged in",ftp->username);
  636.     } else {
  637.         usprintf(ftp->control,loggeda);
  638.         log(ftp->control,"%s logged in, ID %s",ftp->username,pass);
  639.     }
  640. }
  641.  
  642. #ifdef    MSDOS
  643. /* Illegal characters in a DOS filename */
  644. static char badchars[] = "\"[]:|<>+=;,";
  645. #endif
  646.  
  647. /* Return 1 if the file operation is allowed, 0 otherwise */
  648. int
  649. permcheck(path,perms,op,file)
  650. char *path;
  651. int perms;
  652. int op;
  653. char *file;
  654. {
  655.     char *cp, *cp1;
  656.  
  657.     if(file == NULLCHAR || path == NULLCHAR)
  658.         return 0;    /* Probably hasn't logged in yet */
  659.  
  660. /* To get to the CDROM - EVERYBODY gets read privs, regardless of what
  661.   /ftpusers has to say about it!!! - kb7yw */
  662.  
  663. #ifdef CALLSERVER
  664.       if (CDROM != NULLCHAR && strncmp(file, CDROM ,2) == 0) {
  665.       /* Check for characters illegal in MS-DOS file names */
  666.       for(cp = badchars;*cp != '\0';cp++){
  667.         if(strchr(&file[2],*cp) != NULLCHAR)
  668.         return 0;
  669.       }
  670.  
  671.         switch(op){ /* What to do when the user is on the cd-rom drive      */
  672.         case RETR_CMD: /* Everybody gets read privs regardless of ftpusers  */
  673.           /* User has permission to read files */
  674.             return 1;
  675.         case DELE_CMD:
  676.         case RMD_CMD:
  677.           /* User must not have permission to (over)write files */
  678.         case STOR_CMD:
  679.         case MKD_CMD:
  680.           /* User must NOT have permission to (over)write files
  681.            */
  682.           return 0;
  683.         }   /* switch(op) */
  684.       }     /* if strncmp(....  */
  685. #endif    /* #ifdef CALLSERVER  */
  686. #ifndef MAC
  687.     /* The target file must be under the user's allowed search path */
  688.     /* We let them specify multiple paths using path;path... -russ */
  689.     for(cp = path;;cp = cp1+1){
  690.         if((cp1 = strchr(cp,';')) == NULLCHAR)
  691.             cp1 = strchr(cp,'\0');
  692.         if((strncmp(file,cp,cp1 - cp)) == 0)
  693.             break;
  694.         if(*cp1 == '\0')
  695.             return 0;
  696.     }
  697. #endif
  698. #ifdef    MSDOS
  699.     /* Check for characters illegal in MS-DOS file names */
  700.     for(cp = badchars;*cp != '\0';cp++){
  701.         if(strchr(file,*cp) != NULLCHAR)
  702.             return 0;    
  703.     }
  704. #endif
  705.  
  706.     switch(op){
  707.     case RETR_CMD:
  708.         /* User must have permission to read files */
  709.         if(perms & FTP_READ)
  710.             return 1;
  711.         return 0;
  712.     case DELE_CMD:
  713.     case RMD_CMD:
  714.         /* User must have permission to (over)write files */
  715.         if(perms & FTP_WRITE)
  716.             return 1;
  717.         return 0;
  718.     case STOR_CMD:
  719.     case MKD_CMD:
  720.         /* User must have permission to (over)write files, or permission
  721.          * to create them if the file doesn't already exist
  722.          */
  723.         if(perms & FTP_WRITE)
  724.             return 1;
  725.         if(access(file,2) == -1 && (perms & FTP_CREATE))
  726.             return 1;
  727.         return 0;
  728.     }
  729.     return 0;    /* "can't happen" -- keep lint happy */
  730. }
  731. static int
  732. sendit(ftp,command,file)
  733. struct ftpserv *ftp;
  734. char *command;
  735. char *file;
  736. {
  737.     long total;
  738.     struct sockaddr_in dport;
  739.  
  740.     ftp->data = socket(AF_INET,SOCK_STREAM,0);
  741.     dport.sin_family = AF_INET;
  742.     dport.sin_addr.s_addr = INADDR_ANY;
  743.     dport.sin_port = IPPORT_FTPD;
  744.     bind(ftp->data,(char *)&dport,SOCKSIZE);
  745.     usprintf(ftp->control,sending,command,file);
  746.     if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
  747.         fclose(ftp->fp);
  748.         ftp->fp = NULLFILE;
  749.         close_s(ftp->data);
  750.         ftp->data = -1;
  751.         usprintf(ftp->control,noconn);
  752.         return -1;
  753.     }
  754. #ifdef FTPTDISC
  755.     /* Turn of the timeout timer here, some ftp's could
  756.      * take a long time with sloooow packet channels - WG7J
  757.      */
  758.     stop_timer(&ftp->tdisc);
  759. #endif
  760.  
  761.     /* Do the actual transfer */
  762.     total = sendfile(ftp->fp,ftp->data,ftp->type,0);
  763.  
  764. #ifdef FTPTDISC
  765.     /* And turn it back on now */
  766.     start_timer(&ftp->tdisc);
  767. #endif
  768.     if(total == -1){
  769.         /* An error occurred on the data connection */
  770.         usprintf(ftp->control,noconn);
  771.         shutdown(ftp->data,2);    /* Blow away data connection */
  772.     } else {
  773.         usprintf(ftp->control,txok);
  774.     }
  775.     fclose(ftp->fp);
  776.     ftp->fp = NULLFILE;
  777.     close_s(ftp->data);
  778.     ftp->data = -1;
  779.     if(total == -1)
  780.         return -1;
  781.     else
  782.         return 0;
  783. }
  784. static int
  785. recvit(ftp,command,file)
  786. struct ftpserv *ftp;
  787. char *command;
  788. char *file;
  789. {
  790.     struct sockaddr_in dport;
  791.     long total;
  792.  
  793.     ftp->data = socket(AF_INET,SOCK_STREAM,0);
  794.     dport.sin_family = AF_INET;
  795.     dport.sin_addr.s_addr = INADDR_ANY;
  796.     dport.sin_port = IPPORT_FTPD;
  797.     bind(ftp->data,(char *)&dport,SOCKSIZE);
  798.     usprintf(ftp->control,sending,command,file);
  799.     if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
  800.         fclose(ftp->fp);
  801.         ftp->fp = NULLFILE;
  802.         close_s(ftp->data);
  803.         ftp->data = -1;
  804.         usprintf(ftp->control,noconn);
  805.         return -1;
  806.     }
  807. #ifdef FTPTDISC
  808.     /* Turn of the timeout timer here; some ftp's could
  809.      * take a long time with sloooow packet channels - WG7J
  810.      */
  811.     stop_timer(&ftp->tdisc);
  812. #endif
  813.  
  814.     /* Do the actual transfer */
  815.     total = recvfile(ftp->fp,ftp->data,ftp->type,0);
  816.  
  817. #ifdef FTPTDISC
  818.     /* And turn it back on now */
  819.     start_timer(&ftp->tdisc);
  820. #endif
  821.  
  822. #ifdef    CPM
  823.     if(ftp->type == ASCII_TYPE)
  824.         putc(CTLZ,ftp->fp);
  825. #endif
  826.     if(total == -1) {
  827.         /* An error occurred while writing the file */
  828.         usprintf(ftp->control,writerr, strerror(errno));
  829.         shutdown(ftp->data,2);    /* Blow it away */
  830.     } else {
  831.         usprintf(ftp->control,rxok);
  832.         close_s(ftp->data);
  833.     }
  834.     ftp->data = -1;
  835.     fclose(ftp->fp);
  836.     ftp->fp = NULLFILE;
  837.     if(total == -1)
  838.         return -1;
  839.     else
  840.         return 0;
  841. }
  842.